home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / AreaAveragingScaleFilter.java < prev    next >
Text File  |  1998-09-22  |  7KB  |  231 lines

  1. /*
  2.  * @(#)AreaAveragingScaleFilter.java    1.4 98/07/01
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.awt.image;
  16.  
  17. import java.awt.image.ImageConsumer;
  18. import java.awt.image.ColorModel;
  19. import java.util.Hashtable;
  20. import java.awt.Rectangle;
  21.  
  22. /**
  23.  * An ImageFilter class for scaling images using a simple area averaging
  24.  * algorithm that produces smoother results than the nearest neighbor
  25.  * algorithm.
  26.  * This class extends the basic ImageFilter Class to scale an existing
  27.  * image and provide a source for a new image containing the resampled
  28.  * image.  The pixels in the source image are blended to produce pixels
  29.  * for an image of the specified size.  The blending process is analogous
  30.  * to scaling up the source image to a multiple of the destination size
  31.  * using pixel replication and then scaling it back down to the destination
  32.  * size by simply averaging all the pixels in the supersized image that
  33.  * fall within a given pixel of the destination image.  If the data from
  34.  * the source is not delivered in TopDownLeftRight order then the filter
  35.  * will back off to a simple pixel replication behavior and utilize the
  36.  * requestTopDownLeftRightResend() method to refilter the pixels in a
  37.  * better way at the end.
  38.  * It is meant to be used in conjunction with a FilteredImageSource
  39.  * object to produce scaled versions of existing images.
  40.  *
  41.  * @see FilteredImageSource
  42.  * @see ReplicateImageFilter
  43.  * @see ImageFilter
  44.  *
  45.  * @version    1.4 07/01/98
  46.  * @author     Jim Graham
  47.  */
  48. public class AreaAveragingScaleFilter extends ReplicateScaleFilter {
  49.     private static final ColorModel rgbmodel = ColorModel.getRGBdefault();
  50.     private static final int neededHints = (TOPDOWNLEFTRIGHT
  51.                         | COMPLETESCANLINES);
  52.  
  53.     private boolean passthrough;
  54.     private float reds[], greens[], blues[], alphas[];
  55.     private int savedy;
  56.     private int savedyrem;
  57.  
  58.     /**
  59.      * Constructs an AreaAveragingScaleFilter that scales the pixels from
  60.      * its source Image as specified by the width and height parameters.
  61.      * @param width the target width to scale the image
  62.      * @param height the target height to scale the image
  63.      */
  64.     public AreaAveragingScaleFilter(int width, int height) {
  65.     super(width, height);
  66.     }
  67.  
  68.     /**
  69.      * Detect if the data is being delivered with the necessary hints
  70.      * to allow the averaging algorithm to do its work.
  71.      * @see ImageConsumer#setHints
  72.      */
  73.     public void setHints(int hints) {
  74.     passthrough = ((hints & neededHints) != neededHints);
  75.     super.setHints(hints);
  76.     }
  77.  
  78.     private void makeAccumBuffers() {
  79.     reds = new float[destWidth];
  80.     greens = new float[destWidth];
  81.     blues = new float[destWidth];
  82.     alphas = new float[destWidth];
  83.     }
  84.  
  85.     private int[] calcRow() {
  86.     float mult = ((float) srcWidth) * srcHeight;
  87.     if (outpixbuf == null || !(outpixbuf instanceof int[])) {
  88.         outpixbuf = new int[destWidth];
  89.     }
  90.     int[] outpix = (int[]) outpixbuf;
  91.     for (int x = 0; x < destWidth; x++) {
  92.         int a = Math.round(alphas[x] / mult);
  93.         int r = Math.round(reds[x] / mult);
  94.         int g = Math.round(greens[x] / mult);
  95.         int b = Math.round(blues[x] / mult);
  96.         if (a < 0) {a = 0;} else if (a > 255) {a = 255;}
  97.         if (r < 0) {r = 0;} else if (r > 255) {r = 255;}
  98.         if (g < 0) {g = 0;} else if (g > 255) {g = 255;}
  99.         if (b < 0) {b = 0;} else if (b > 255) {b = 255;}
  100.         outpix[x] = (a << 24 | r << 16 | g << 8 | b);
  101.     }
  102.     return outpix;
  103.     }
  104.  
  105.     private void accumPixels(int x, int y, int w, int h,
  106.                  ColorModel model, Object pixels, int off,
  107.                  int scansize) {
  108.     if (reds == null) {
  109.         makeAccumBuffers();
  110.     }
  111.     int sy = y;
  112.     int syrem = destHeight;
  113.     int dy, dyrem;
  114.     if (sy == 0) {
  115.         dy = 0;
  116.         dyrem = 0;
  117.     } else {
  118.         dy = savedy;
  119.         dyrem = savedyrem;
  120.     }
  121.     while (sy < y + h) {
  122.         int amty;
  123.         if (dyrem == 0) {
  124.         for (int i = 0; i < destWidth; i++) {
  125.             alphas[i] = reds[i] = greens[i] = blues[i] = 0f;
  126.         }
  127.         dyrem = srcHeight;
  128.         }
  129.         if (syrem < dyrem) {
  130.         amty = syrem;
  131.         } else {
  132.         amty = dyrem;
  133.         }
  134.         int sx = 0;
  135.         int dx = 0;
  136.         int sxrem = 0;
  137.         int dxrem = srcWidth;
  138.         float a = 0f, r = 0f, g = 0f, b = 0f;
  139.         while (sx < w) {
  140.         if (sxrem == 0) {
  141.             sxrem = destWidth;
  142.             int rgb;
  143.             if (pixels instanceof byte[]) {
  144.             rgb = ((byte[]) pixels)[off + sx] & 0xff;
  145.             } else {
  146.             rgb = ((int[]) pixels)[off + sx];
  147.             }
  148.             rgb = model.getRGB(rgb);
  149.             a = rgb >>> 24;
  150.             r = (rgb >> 16) & 0xff;
  151.             g = (rgb >>  8) & 0xff;
  152.             b = rgb & 0xff;
  153.         }
  154.         int amtx;
  155.         if (sxrem < dxrem) {
  156.             amtx = sxrem;
  157.         } else {
  158.             amtx = dxrem;
  159.         }
  160.         float mult = ((float) amtx) * amty;
  161.         alphas[dx] += mult * a;
  162.         reds[dx] += mult * r;
  163.         greens[dx] += mult * g;
  164.         blues[dx] += mult * b;
  165.         if ((sxrem -= amtx) == 0) {
  166.             sx++;
  167.         }
  168.         if ((dxrem -= amtx) == 0) {
  169.             dx++;
  170.             dxrem = srcWidth;
  171.         }
  172.         }
  173.         if ((dyrem -= amty) == 0) {
  174.         int outpix[] = calcRow();
  175.         do {
  176.             consumer.setPixels(0, dy, destWidth, 1,
  177.                        rgbmodel, outpix, 0, destWidth);
  178.             dy++;
  179.         } while ((syrem -= amty) >= amty && amty == srcHeight);
  180.         } else {
  181.         syrem -= amty;
  182.         }
  183.         if (syrem == 0) {
  184.         syrem = destHeight;
  185.         sy++;
  186.         off += scansize;
  187.         }
  188.     }
  189.     savedyrem = dyrem;
  190.     savedy = dy;
  191.     }
  192.  
  193.     /**
  194.      * Combine the components for the delivered byte pixels into the
  195.      * accumulation arrays and send on any averaged data for rows of
  196.      * pixels that are complete.  If the correct hints were not
  197.      * specified in the setHints call then relay the work to our
  198.      * superclass which is capable of scaling pixels regardless of
  199.      * the delivery hints.
  200.      * @see ReplicateScaleFilter
  201.      */
  202.     public void setPixels(int x, int y, int w, int h,
  203.               ColorModel model, byte pixels[], int off,
  204.               int scansize) {
  205.     if (passthrough) {
  206.         super.setPixels(x, y, w, h, model, pixels, off, scansize);
  207.     } else {
  208.         accumPixels(x, y, w, h, model, pixels, off, scansize);
  209.     }
  210.     }
  211.  
  212.     /**
  213.      * Combine the components for the delivered int pixels into the
  214.      * accumulation arrays and send on any averaged data for rows of
  215.      * pixels that are complete.  If the correct hints were not
  216.      * specified in the setHints call then relay the work to our
  217.      * superclass which is capable of scaling pixels regardless of
  218.      * the delivery hints.
  219.      * @see ReplicateScaleFilter
  220.      */
  221.     public void setPixels(int x, int y, int w, int h,
  222.               ColorModel model, int pixels[], int off,
  223.               int scansize) {
  224.     if (passthrough) {
  225.         super.setPixels(x, y, w, h, model, pixels, off, scansize);
  226.     } else {
  227.         accumPixels(x, y, w, h, model, pixels, off, scansize);
  228.     }
  229.     }
  230. }
  231.